#include "updaterdialog.h"
#include "ui_updaterdialog.h"

#include "updaterio.h"

#include "processwrapper.h"

#include <QtGui>

UpdaterDialog::UpdaterDialog(const QString &filename,
                             const QString &installResult,
                             QWidget *parent) :
    QDialog(parent),
    ui(new Ui::UpdaterDialog),
    myInputFilename(filename),
    myInstallResult(installResult)
{
    ui->setupUi(this);

    upd = new UpdaterCore();

    InputData input;
    //input.current_version = 000100;
    input.server = "keyswitcher.sintegrial.com";
    input.version_file = "version.upd";
    input.local_dir = QDir::tempPath();
    input.architecture = "win32";
    input.path_subst["%BIN%"] = qApp->applicationDirPath()+"/";
    input.path_subst["%DATA%"] = qApp->applicationDirPath()+"/data/";

    // get version from registry
    QSettings reg(QSettings::UserScope, "Sintegrial", "KeySwitch");
    input.current_version = reg.value("Version").toUInt();

    //UpdaterIO::exportInfo(input, filename);

    // import info if this is finish of installation
    if (installResult.length())
      UpdaterIO::importInfo(input, filename);

    upd->setInputData(input);

    upd->setHandler(this);

    // update title
    setWindowTitle(QString("Current version: %1").arg(reg.value("VersionTxt").toString()));
}

UpdaterDialog::~UpdaterDialog()
{
    delete ui;

    delete upd;
}

void UpdaterDialog::changeEvent(QEvent *e)
{
    QDialog::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

void UpdaterDialog::closeEvent(QCloseEvent *e)
{
  //upd->shutdown();

  e->accept();
  QDialog::closeEvent(e);
}

void UpdaterDialog::start()
{
  ui->lAction->setText("Getting version info...");
  ui->progressBar->setRange(0,0);
  ui->progressBar->setValue(0);

  QApplication::processEvents();

  int res = upd->getServerVersion();
  if (res <= 0)
  {
    ui->lAction->setText(QString("Unable to get version info (code returned: %1)").arg(res));
    return;
  }

  VersionInfo info = upd->getInfo();
  if (info.latest_version <= upd->getInputData().current_version)
  {
    ui->lAction->setText("No update found.");
    ui->progressBar->setRange(0,100);
    ui->progressBar->setValue(100);
    return;
  }

  ui->lAction->setText(QString("Newer version found: %1").arg(info.txt_version));

  if (QMessageBox::question(0, "Update available",
                            QString("Newer version found: %1\n"
                                    "Files to download: %2")
                            .arg(info.txt_version)
                            .arg(info.modules.count()),
                            QMessageBox::Apply, QMessageBox::Cancel) == QMessageBox::Cancel)
  {
    close();
    return;
  }

  // setup gui
  ui->progressBar->setRange(0,info.modules.count()+1);
  ui->progressBar->setValue(0);
  QApplication::processEvents();

  //res = upd->updateAll();
  res = upd->downloadModules();
  if (res <= 0) {
    ui->lAction->setText("Download errors detected.");
    return;
  }

  // kill processes
  unsigned pid_conf = ProcessWrapper::findProcess("keyconfig");
  ProcessWrapper::terminateProcess(pid_conf, 2000);
  unsigned pid_switch = ProcessWrapper::findProcess("keyswitch");
  ProcessWrapper::terminateProcess(pid_switch, 2000);

  QString configPath = qApp->applicationDirPath() + "/keyconfig.exe";
  QString switchPath = qApp->applicationDirPath() + "/keyswitch.exe";

  InputData input = upd->getInputData();
  input.run_after_dir = qApp->applicationDirPath();
  if (pid_switch)
    input.run_after = switchPath;

  UpdaterIO::exportInfo(input, myInputFilename);


  // detach installer module

//  QStringList files;
//  files << "mingwm10.dll" << "zlib.dll"
//      << "QtCore4.dll" << "QtGui4.dll" << "QtNetwork4.dll" << "updater.exe";
//  QString local_dir = upd->getInputData().local_dir;
//
//  QStringList args;
//  res = detachAndRun(local_dir, files, qApp->applicationFilePath(), args);

  QString installfile(upd->getInputData().local_dir + "/install.lst");
  upd->writeInstallList(installfile);
  bool r = QProcess::startDetached(
      qApp->applicationDirPath() + "/extract.exe",
      QStringList() << /*qApp->applicationFilePath()*/configPath <<  myInputFilename << installfile,
      qApp->applicationDirPath()
      );

  if (!r)
    ui->lAction->setText("Can not run installer.");
  else
    close();
}

/*
int UpdaterDialog::detachAndRun(const QString &local_dir,
                                const QStringList &files,
                                const QString &exe_name,
                                const QStringList &args)
{
  QString installName(local_dir + "/" + "install.lst");
  upd->writeInstallList(installName);

  // copy
  QString dirname = QFileInfo(local_dir).canonicalFilePath();
  dirname.replace("/", "\\");

  QString fname(dirname + "/run.cmd");
  QFile out(fname);
  if (!out.open(QFile::WriteOnly))
    return -1;
  QTextStream ts(&out);

  for (int i = 0; i < files.count(); i++)
  {
    QString filename = qApp->applicationDirPath() + "/" + files.at(i);
    filename = QFileInfo(filename).canonicalFilePath();
    filename.replace("/", "\\");
    if (filename.isEmpty())
      continue;

//    ui->lAction->setText(QString("Copying %1 to %2...").arg(filename, dirname));
//    qApp->processEvents();

//    int res = QProcess::execute("command",
//                    QStringList() << "copy" << "/Y" << filename << dirname);
//    if (res)
//      return -1;
    ts << "copy /Y \"" << filename << "\" \"" << dirname << "\"\n";
  }

  ui->lAction->setText("Running installer...");
  qApp->processEvents();

  // start
  ts << "\"" << exe_name << "\" \"" << myInputFilename << "\" /i \"" << installName << "\"\n";
  out.close();

  QDir::setCurrent(dirname);
  bool res = QProcess::startDetached(fname);
  if (!res)
    return -2;

  qApp->exit(0);
  exit(0);
  return 0;
}
*/

//void UpdaterDialog::setInstallList(const QString &list_name)
//{
//  myInstallFilename = list_name;
//}
//
//void UpdaterDialog::install()
//{
//  ui->lAction->setText("Installing...");
//  qApp->processEvents();
//
//  int res = upd->installModules(myInstallFilename);
//  if (res <= 0)
//    ui->lAction->setText("Can not run installer.");
//  else
//    ui->lAction->setText("Installed ok.");
//}

void UpdaterDialog::onModuleDownload(const ModuleInfo &mi)
{
  ui->lAction->setText(QString("Downloading: %1").arg(mi.file_name));
  ui->progressBar->setValue(ui->progressBar->value()+1);
  QApplication::processEvents();
}

void UpdaterDialog::onModuleInstall(const ModuleInfo &mi)
{
  ui->lAction->setText(QString("Installing: %1").arg(mi.file_name));
  ui->progressBar->setValue(ui->progressBar->value()+1);
  QApplication::processEvents();
}

void UpdaterDialog::onFinished()
{
  ui->lAction->setText("Update finished.");
  ui->progressBar->setRange(0,1);
  ui->progressBar->setValue(1);

  upd->runDelayed();
}

void UpdaterDialog::on_pbCancel_clicked()
{
  close();
}



void UpdaterDialog::installFinished()
{
  onFinished();

  if (myInstallResult == "/res:ok")
    ui->lAction->setText("Updated successfully.");
  else if (myInstallResult.startsWith("/res:unzip_failed"))
    ui->lAction->setText("Update finished with problems.");
  else
    ui->lAction->setText("Update failed.");
}
